from meta_service.ucentre import AnyLancer,AnyTag

class EntrySet:

    def __init__(self,entry_id_all:list|set=None):
        self.entry_id_set = set()
        if entry_id_all is not None:
            self.__add_some_entry_id(entry_id_all)

    def __fill_by_tag(self,key,value=None):
        idset = AnyTag.GetEntryIdsOfTag(key,value)
        if isinstance(idset,set) and len(idset) > 0:
            self.__add_some_entry_id(idset)

    def __add_some_entry_id(self,entry_id_all):
        cannot_add_in = set()
        for entry_id in entry_id_all:
            if not self.__add_entry_id(str(entry_id)):
                cannot_add_in.add(str(entry_id))
        if len(cannot_add_in) > 0:
            print(f"cannot add these entry_id: {cannot_add_in}")

    def __check_entry_valid(self,entry_id) -> bool:
        return AnyLancer.ExistEntryId(entry_id)

    def __add_entry_id(self,entry_id) -> bool:
        if entry_id in self.entry_id_set:
            return True
        if self.__check_entry_valid(entry_id):
            self.entry_id_set.add(entry_id)
            return True
        return False

    def __len__(self):
        return len(self.entry_id_set)

    def FillByTag(self,key:str,value:str=None):
        self.__fill_by_tag(key,value)
    
    def DumpEntryIdSet(self) -> set:
        return self.entry_id_set.copy()
    
    def AddEntryId(self,entry_id) -> bool:
        return self.__add_entry_id(entry_id)
    
    def AddEntryIds(self,entry_id_all:list|set=None):
        self.entry_id_set = set()
        if entry_id_all is not None:
            self.__add_some_entry_id(entry_id_all)
   
    def Size(self):
        return len(self.entry_id_set)
    
    def Filter(self,filter_func):
        ft_out_set = set()
        for entry_id in self.entry_id_set:
            stat = False
            try:
                stat = filter_func(entry_id)
            except Exception as e:
                print(f"error when filter entry_id: {entry_id}, err: {str(e)}")
                continue
            if stat:
                ft_out_set.add(entry_id)
        return EntrySet(ft_out_set)
    
    def PipeTag(self,tag_generate_func):
        for entry_id in self.entry_id_set:
            tags = {}
            try:
                tags = dict(tag_generate_func(entry_id))
            except Exception as e:
                print(f"error when generate tag for entry_id: {entry_id}, err: {str(e)}")
                continue
            at = AnyTag(entry_id)
            for name,value in tags.items():
                at.AddTag(name,value)
        return self
    
    def Merge(self,es):
        if not isinstance(es,EntrySet):
            raise Exception("merge set is not EntrySet")
        newly_set = set(self.entry_id_set)
        newly_set = newly_set | es.DumpEntryIdSet()
        return EntrySet(newly_set)


"""
# input:  entry_id
# output: bool
# note:   you can load this entry with id by AnyLancer or AnyTag tools etc...
def filter_func(entry_id) -> bool:
    # make some check
    return False
"""


